﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Biomedica.Graphics
{
    public class Vector2
    {
        public float X { set; get; }
        public float Y { set; get; }
      

        public Vector2(float x, float y)
        {
            X = x;
            Y = y;
            
        }

        public static Vector2 operator +(Vector2 v1, Vector2 v2)
        {
            return new Vector2(v1.X + v2.X, v1.Y + v2.Y);
        }
        public static Vector2 operator +(Vector2 v, float d)
        {
            return new Vector2(v.X + d, v.Y + d);
        }
        public static Vector2 operator +(Vector2 v, double d)
        {
            return new Vector2(v.X + (float)d, v.Y + (float)d);
        }


        public static Vector2 operator -(Vector2 v1, Vector2 v2)
        {
            return new Vector2(v1.X - v2.X, v1.Y - v2.Y);
        }
        public static Vector2 operator -(Vector2 v, double d)
        {
            return new Vector2(v.X -(float) d, v.Y -(float) d);
        }
        public static Vector2 operator -(Vector2 v, float d)
        {
            return new Vector2(v.X - d, v.Y - d);
        }
        public static Vector2 operator *(Vector2 v1, Vector2 v2)
        {
            return new Vector2(v1.X * v2.X, v1.Y * v2.Y);
        }
        public static Vector2 operator /(Vector2 v1, Vector2 v2)
        {
            return new Vector2(v1.X / v2.X, v1.Y / v2.Y);
        }
        public static Vector2 operator /(float f, Vector2 v2)
        {
            return new Vector2(f / v2.X, f / v2.Y);
        }
        public static Vector2 operator /( Vector2 v2,float f)
        {
            return new Vector2(v2.X/f,  v2.Y/f);
        }
        public static Vector2 operator *(Vector2 v, float d)
        {
            return new Vector2(v.X * d, v.Y * d);
        }
        public static Vector2 operator *(Vector2 v, double d)
        {
            return new Vector2(v.X * (float)d, v.Y * (float)d);
        }
        public static Boolean operator &(Vector2 v1, Vector2 v2)
        {
            return (v1.X == v2.X) & (v1.Y == v2.Y) ;
        }
        public static Boolean operator |(Vector2 v1, Vector2 v2)
        {
            return (v1.X == v2.X) | (v1.Y == v2.Y);
        }

        public static Boolean operator <(Vector2 v1, Vector2 v2)
        {
            return (v1.X < v2.X) && (v1.Y < v2.Y);
        }
        public static Boolean operator >(Vector2 v1, Vector2 v2)
        {
            return (v1.X > v2.X) && (v1.Y > v2.Y);
        }
        public static Boolean operator <=(Vector2 v1, Vector2 v2)
        {
            return (v1.X <= v2.X) && (v1.Y <= v2.Y);
        }
        public static Boolean operator >=(Vector2 v1, Vector2 v2)
        {
            return (v1.X >= v2.X) && (v1.Y >= v2.Y);
        }

        public double Distance(Vector2 v1, Vector2 v2)
        {
            return System.Math.Sqrt(((v1.X - v2.X) * (v1.X - v2.X)) + ((v1.X - v2.Y) * (v1.X - v2.Y)));
        }

        public static Vector2 Zero
        {
            get { return new Vector2(0, 0); }
        }

        public static Vector2 One
        {
            get { return new Vector2(1, 1); }
        }

        public bool HasValue { get; set; }

       
        public float Distance()
        {
            return (float)(Math.Sqrt((X * X) + (Y * Y)));
        }
    }

    public class Vector3
    {
        public float X { set; get; }
        public float Y {set;get;}
        public float Z{set;get;}
        public Vector3 Theta { set; get; }

        public Vector3(float x, float y, float z)
        {
            X = x;
            Y = y;
            Z = z;
           
                float thetaX = (float)System.Math.Acos(X / Resultant());
                float thetaY = (float)System.Math.Acos(Y / Resultant());
                float thetaZ = (float)System.Math.Acos(Z / Resultant());
               // if (!float.IsNaN(thetaX) && !float.IsNaN(thetaY) && !float.IsNaN(thetaZ))
             //       Theta = new Vector3(thetaX, thetaY, thetaZ);
             //   else Theta = Vector3.Zero;
           
        }

        public static Vector3 operator +(Vector3 v1, Vector3 v2)
        {
            return new Vector3(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);

        }
        public static Vector3 operator -(Vector3 v1, Vector3 v2)
        {
            return new Vector3(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
        }
        public static Vector3 operator *(Vector3 v1, Vector3 v2)
        {
            return new Vector3(v1.X * v2.X, v1.Y * v2.Y, v1.Z * v2.Z);
        }
        public static Vector3 operator /(Vector3 v1, Vector3 v2)
        {
            return new Vector3(v1.X / v2.X, v1.Y / v2.Y, v1.Z / v2.Z);
        }
        public static Vector3 operator /(Vector3 v, float d)
        {
            return new Vector3(v.X / d, v.Y / d, v.Z / d);
        }
        public static Boolean operator &(Vector3 v1, Vector3 v2)
        {
            return (v1.X == v2.X) & (v1.Y == v2.Y)&( v1.Z== v2.Z);
        }
        public static Boolean operator |(Vector3 v1, Vector3 v2)
        {
            return (v1.X == v2.X) | (v1.Y == v2.Y) | (v1.Z == v2.Z);
        }
        public double Distance(Vector3 v1, Vector3 v2)
        {
            return System.Math.Sqrt(((v1.X - v2.X) * (v1.X - v2.X)) + ((v1.Y - v2.Y) * (v1.Y- v2.Y)) + ((v1.Z - v2.Z) * (v1.Z - v2.Z)));
        }
        public static Vector3 Zero
        {
            get { return new Vector3(0, 0, 0); }
        }
        public static Vector3 One
        {
            get { return new Vector3(1, 1, 1); }
        }
        public double Resultant()
        {
            return System.Math.Sqrt((X * X) + (Y * Y) + (Z * Z));
        }
        public double Resultant(Vector3 v)
        {
            float dx=X-v.X;
            float dy=Y-v.Y;
            float dz=Z-v.Z;
            return System.Math.Sqrt((dx*dx) + (dy *dy) + (dz*dz));
        }


        internal Vector3 Distance(Vector3 v)
        {
            float dx = X - v.X;
            float dy = Y - v.Y;
            float dz = Z - v.Z;
            return new Vector3(dx, dy, dz);
        }
    }
   
    public class Vector4
    {
        public float Left { set; get; }
        public float Top { set; get; }
        public float Right { set; get; }
        public float Buttom { set; get; }
        public Vector2 Center
        {
            get
            {
                return new Vector2((Left - Right) / 2, (Top - Buttom) / 2);
            }
        }

        public Vector4(float left, float top, float right,float buttom)
        {
            Left = left;
            Top = top;
            Right = right;
            Buttom = buttom;
        }

        public static Vector4 operator +(Vector4 v1, Vector4 v2)
        {
            return new Vector4(v1.Left + v2.Left, v1.Top + v2.Top, v1.Right + v2.Right,v1.Buttom+v2.Buttom);

        }
        public static Vector4 operator -(Vector4 v1, Vector4 v2)
        {
            return new Vector4(v1.Left - v2.Left, v1.Top - v2.Top, v1.Right - v2.Right, v1.Buttom - v2.Buttom);
        }
        public static Vector4 operator *(Vector4 v1, Vector4 v2)
        {
            return new Vector4(v1.Left * v2.Left, v1.Top * v2.Top, v1.Right * v2.Right, v1.Buttom * v2.Buttom);
        }
        public static Vector4 operator /(Vector4 v1, Vector4 v2)
        {
            return new Vector4(v1.Left / v2.Left, v1.Top / v2.Top, v1.Right / v2.Right, v1.Buttom + v2.Buttom);
        }
        public static Boolean operator &(Vector4 v1, Vector4 v2)
        {
            return (v1.Left == v2.Left) & (v2.Right == v2.Right) & (v1.Top == v2.Top)&(v1.Buttom==v2.Buttom);
        }
        public static Boolean operator |(Vector4 v1, Vector4 v2)
        {
            return (v1.Left == v2.Left) | (v2.Right == v2.Right) | (v1.Top == v2.Top) | (v1.Buttom == v2.Buttom);
        }
        public static Boolean operator ==(Vector4 v1, Vector4 v2)
        {
            return (v1.Left == v2.Left) & (v2.Right == v2.Right) & (v1.Top == v2.Top)&(v1.Buttom==v2.Buttom);
        }
        public static Boolean operator !=(Vector4 v1, Vector4 v2)
        {
            return (v1.Left != v2.Left) & (v2.Right != v2.Right) & (v1.Top != v2.Top) & (v1.Buttom != v2.Buttom);
        }
        public static Vector4 Zero
        {
            get { return new Vector4(0, 0, 0,0); }
        }
        public static Vector4 One
        {
            get { return new Vector4(1, 1,1, 1); }
        }
        public Boolean Vector2InBound(Vector2 v)
        {
           // System.Diagnostics.Trace.WriteLine(v.X.ToString() + "," + v.Y.ToString() + "," + Left.ToString() + "," + Top.ToString() + "," + Buttom.ToString() + "," + Right.ToString());
            return (v.X > Left) & (v.X < Right) & (v.Y > Top) & (v.Y < Buttom);
            
        }
        public Boolean IsVectorIntersect(Vector4 v)
        {
            return (v.Left < Left) | (v.Right > Right) | (v.Top > Top) | (v.Buttom < Buttom);
        }
        public bool Equals(Vector4 obj)
        {
           
            return this==obj;
        }
        public Double Distance(Vector2 v)
        {

            return 0;
        }

        internal bool Vector2InBound(System.Windows.Point v)
        {
            return (v.X > Left) & (v.X < Right) & (v.Y > Top) & (v.Y < Buttom);
        }
    }
    public class TimeVectored
    {
        public float X { set; get; }
        public float Y { set; get; }
        public float Z { set; get; }
        public float Time { set; get; }
 
        public TimeVectored(float x, float y, float z, float t)
        {
            X = x;
            Y = y;
            Z = z;
            Time = t;
        }

        public static TimeVectored operator +(TimeVectored v1, TimeVectored v2)
        {
            return new TimeVectored(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z, v1.Time);

        }
        public static TimeVectored operator -(TimeVectored v1, TimeVectored v2)
        {
            return new TimeVectored(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z, v1.Time);
        }
        public static TimeVectored operator *(TimeVectored v1, TimeVectored v2)
        {
            return new TimeVectored(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z, v1.Time);
        }
        public static TimeVectored operator /(TimeVectored v1, TimeVectored v2)
        {
            return new TimeVectored(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z, v1.Time);
        }
        public static Boolean operator &(TimeVectored v1, TimeVectored v2)
        {
            return (v1.X == v2.X) & (v2.Y == v2.Y) & (v1.Z == v2.Z) & (v1.Time == v2.Time);
        }
        public static Boolean operator |(TimeVectored v1, TimeVectored v2)
        {
            return (v1.X == v2.X) | (v2.Y == v2.Y) | (v1.Z == v2.Z) | (v1.Time == v2.Time);
        }
        public static TimeVectored Zero
        {
            get { return new TimeVectored(0, 0, 0, 0); }
        }
        public static TimeVectored One
        {
            get { return new TimeVectored(1, 1, 1, 1); }
        }
      
    }
}
